package services

import (
	"easyShop/core/database/mysql"
	"easyShop/model"
	"errors"
	"github.com/shopspring/decimal"
	"gorm.io/gorm"
	"strconv"
)

func CreateOrder(userId int64, products []model.ProductData) (model.Order, error) {
	// 把客户端的商品ID组成数组
	var productIds []uint
	for _, v := range products {
		productIds = append(productIds, v.ProductId)
	}

	mysqlConnect := mysql.GetConnect()
	var productList []model.Product
	mysqlConnect.Find(&productList, productIds)

	// 把数据库里面商品列表以ID为Key转为map
	var productOfIdMap = make(map[uint]model.Product)
	for _, v := range productList {
		productOfIdMap[v.Id] = v
	}

	// 判断客户端的数据和数据库数据是否符合业务
	totalPriceDecimal := decimal.NewFromFloat(0)
	for _, v := range products {
		if productOfIdMap[v.ProductId].Id == 0 {
			return model.Order{}, errors.New("商品ID(" + strconv.Itoa(int(v.ProductId)) + ")不存在")
		}
		if (productOfIdMap[v.ProductId].Stock - v.Quantity) < 0 {
			return model.Order{}, errors.New("商品ID(" + strconv.Itoa(int(v.ProductId)) + ")库存不足")
		}
		// 获取总价，因为精度问题需要使用decimal包，官方推荐
		totalPriceDecimal = totalPriceDecimal.Add(decimal.NewFromFloat32(productOfIdMap[v.ProductId].Price).Mul(decimal.NewFromInt(int64(v.Quantity))))
	}

	totalPrice64, parseErr := totalPriceDecimal.Float64()
	if parseErr == true {
		return model.Order{}, errors.New("获取订单总价错误")
	}
	totalPrice := float32(totalPrice64)

	var orderData model.Order
	err := mysqlConnect.Transaction(func(tx *gorm.DB) error {
		// 扣除库存
		var orderDetailListData []model.OrderDetail
		var orderProductSnapshotListData []model.OrderProductSnapshot
		for _, product := range products {
			err := tx.Model(&model.Product{}).
				Where("id = ?", product.ProductId).
				Where("stock >= ?", product.Quantity).
				Save(map[string]interface{}{"stock": gorm.Expr("stock - ?", product.Quantity)}).Error
			if err != nil {
				return errors.New("商品ID(" + strconv.Itoa(int(product.ProductId)) + ")库存不足")
			}

			// 商品数据写入es
			currentProductInfo := productOfIdMap[product.ProductId]
			currentProductInfo.Stock = productOfIdMap[product.ProductId].Stock - product.Quantity
			SetProductInfoToEs(currentProductInfo)

			// 组装订单详情数据
			orderDetailListData = append(orderDetailListData, model.OrderDetail{OrderId: 0, ProductId: product.ProductId, Quantity: product.Quantity, Price: productOfIdMap[product.ProductId].Price, TotalPrice: productOfIdMap[product.ProductId].Price * float32(product.Quantity)})
		}
		// 创建订单
		orderData = model.Order{UserId: userId, TotalPrice: totalPrice, OrderStatus: 0, PaymentStatus: 0, DeliveryStatus: 0}
		tx.Create(&orderData)
		// 创建订单详情
		for k, _ := range orderDetailListData {
			orderDetailListData[k].OrderId = orderData.Id

		}

		tx.Model(&model.OrderDetail{}).Create(orderDetailListData)
		// 创建商品数据快照
		for _, v := range orderDetailListData {
			orderProductSnapshotListData = append(orderProductSnapshotListData, model.OrderProductSnapshot{
				OrderDetailId: v.Id,
				Name:          productOfIdMap[v.ProductId].Name,
				Price:         productOfIdMap[v.ProductId].Price,
				Stock:         productOfIdMap[v.ProductId].Stock,
				Description:   productOfIdMap[v.ProductId].Description,
				Detail:        productOfIdMap[v.ProductId].Detail,
			})
		}

		tx.Model(&model.OrderProductSnapshot{}).Create(orderProductSnapshotListData)

		return nil
	})
	if err != nil {
		return model.Order{}, err
	}

	return orderData, nil
}
